﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Xml;

namespace DCT.View
{
    public class CustomTypeDescription
    {
        public string Category { get; set; }
        public string DisplayName { get; set; }
        public string Description { get; set; }
        public bool IsReadOnly { get; set; }
    }

    public class CustomProperty : ICustomTypeDescriptor
    {
        //当前选择对象
        private object mCurrentSelectObject;
        private Dictionary<string, CustomTypeDescription> mObjectAttribs = new Dictionary<string, CustomTypeDescription>();
        public CustomProperty(object pSelectObject, XmlNodeList pObjectPropertys)
        {
            mCurrentSelectObject = pSelectObject;
            XmlNode tmpXNode;
            IEnumerator tmpIe = pObjectPropertys.GetEnumerator();
            while (tmpIe.MoveNext())
            {
                tmpXNode = tmpIe.Current as XmlNode;

                string tmpName;
                string tmpCategory;
                string tmpDisplayName;
                string tmpDescription;
                bool tmpIsReadOnly;

                try
                {
                    tmpName = tmpXNode.Attributes["Name"].Value;
                }
                catch
                {
                    continue;
                }

                try
                {
                    tmpCategory = tmpXNode.Attributes["Category"].Value;
                }
                catch
                {
                    tmpCategory = string.Empty;
                }

                try
                {
                    tmpDisplayName = tmpXNode.Attributes["DisplayName"].Value;
                }
                catch
                {
                    continue;
                }

                try
                {
                    tmpDescription = tmpXNode.Attributes["Description"].Value;
                }
                catch
                {
                    tmpDescription = string.Empty;
                }

                try
                {
                    tmpIsReadOnly = bool.Parse(tmpXNode.Attributes["IsReadOnly"].Value);
                }
                catch
                {
                    tmpIsReadOnly = false;
                }

                mObjectAttribs.Add(tmpName, new CustomTypeDescription { Category = tmpCategory, DisplayName = tmpDisplayName, Description = tmpDescription, IsReadOnly = tmpIsReadOnly });
            }
        }
        #region ICustomTypeDescriptor Members
        public AttributeCollection GetAttributes()
        {
            return TypeDescriptor.GetAttributes(mCurrentSelectObject);
        }
        public string GetClassName()
        {
            return TypeDescriptor.GetClassName(mCurrentSelectObject);
        }
        public string GetComponentName()
        {
            return TypeDescriptor.GetComponentName(mCurrentSelectObject);
        }
        public TypeConverter GetConverter()
        {
            return TypeDescriptor.GetConverter(mCurrentSelectObject);
        }
        public EventDescriptor GetDefaultEvent()
        {
            return TypeDescriptor.GetDefaultEvent(mCurrentSelectObject);
        }
        public PropertyDescriptor GetDefaultProperty()
        {
            return TypeDescriptor.GetDefaultProperty(mCurrentSelectObject);
        }
        public object GetEditor(Type editorBaseType)
        {
            return TypeDescriptor.GetEditor(mCurrentSelectObject, editorBaseType);
        }
        public EventDescriptorCollection GetEvents(Attribute[] attributes)
        {
            return TypeDescriptor.GetEvents(mCurrentSelectObject, attributes);
        }
        public EventDescriptorCollection GetEvents()
        {
            return TypeDescriptor.GetEvents(mCurrentSelectObject);
        }
        public PropertyDescriptorCollection GetProperties(Attribute[] attributes)
        {
            List<CustomPropertyDescriptor> tmpPDCLst = new List<CustomPropertyDescriptor>();
            PropertyDescriptorCollection tmpPDC = TypeDescriptor.GetProperties(mCurrentSelectObject, attributes);
            IEnumerator tmpIe = tmpPDC.GetEnumerator();
            CustomPropertyDescriptor tmpCPD;
            PropertyDescriptor tmpPD;
            while (tmpIe.MoveNext())
            {
                tmpPD = tmpIe.Current as PropertyDescriptor;
                if (mObjectAttribs.ContainsKey(tmpPD.Name))
                {
                    tmpCPD = new CustomPropertyDescriptor(mCurrentSelectObject, tmpPD);
                    tmpCPD.SetDisplayName(mObjectAttribs[tmpPD.Name].DisplayName);
                    tmpCPD.SetCategory(mObjectAttribs[tmpPD.Name].Category);
                    tmpCPD.SetDescription(mObjectAttribs[tmpPD.Name].Description);
                    tmpCPD.SetIsReadOnly(mObjectAttribs[tmpPD.Name].IsReadOnly);
                    //tmpCPD.SetCategory(tmpPD.Category + "");
                    tmpPDCLst.Add(tmpCPD);
                }
            }
            return new PropertyDescriptorCollection(tmpPDCLst.ToArray());
        }
        public PropertyDescriptorCollection GetProperties()
        {
            return TypeDescriptor.GetProperties(mCurrentSelectObject);
        }
        public object GetPropertyOwner(PropertyDescriptor pd)
        {
            return mCurrentSelectObject;
        }
        #endregion
        public class CustomPropertyDescriptor : PropertyDescriptor
        {
            private PropertyDescriptor mProp;
            private object mComponent;

            public CustomPropertyDescriptor(object pComponent, PropertyDescriptor pPD)
                : base(pPD)
            {
                mCategory = base.Category;
                mDisplayName = base.DisplayName;
                mProp = pPD;
                mComponent = pComponent;
            }
            private string mCategory;
            public override string Category
            {
                get { return mCategory; }
            }
            private string mDisplayName;
            public override string DisplayName
            {
                get { return mDisplayName; }
            }
            public void SetDisplayName(string pDispalyName)
            {
                mDisplayName = pDispalyName;
            }
            public void SetCategory(string pCategory)
            {
                mCategory = pCategory;
            }

            private string mDescription;
            public override string Description
            {
                get { return mDescription; }
            }
            public void SetDescription(string pDescription)
            {
                mDescription = pDescription;
            }

            private bool mIsReadOnly;
            public override bool IsReadOnly
            {
                get { return mIsReadOnly; }
            }
            public void SetIsReadOnly(bool pIsReadOnly)
            {
                mIsReadOnly = pIsReadOnly;
            }

            public override bool CanResetValue(object component)
            {
                return mProp.CanResetValue(component);
            }

            public override Type ComponentType
            {
                get { return mProp.ComponentType; }
            }

            public override object GetValue(object component)
            {
                return mProp.GetValue(component);
            }

            public override Type PropertyType
            {
                get { return mProp.PropertyType; }
            }

            public override void ResetValue(object component) 
            { 
                mProp.ResetValue(component); 
            }

            public override void SetValue(object component, object value) 
            { 
                mProp.SetValue(component, value); 
            }

            public override bool ShouldSerializeValue(object component)
            {
                return mProp.ShouldSerializeValue(component);
            }
        }
    }
}
